!! Copyright (C) 2009,2010,2011,2012  Marco Restelli
!!
!! This file is part of:
!!   LDGH -- Local Hybridizable Discontinuous Galerkin toolkit
!!
!! LDGH is free software: you can redistribute it and/or modify it
!! under the terms of the GNU General Public License as published by
!! the Free Software Foundation, either version 3 of the License, or
!! (at your option) any later version.
!!
!! LDGH is distributed in the hope that it will be useful, but WITHOUT
!! ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
!! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
!! License for more details.
!!
!! You should have received a copy of the GNU General Public License
!! along with LDGH. If not, see <http://www.gnu.org/licenses/>.
!!
!! author: Marco Restelli                   <marco.restelli@gmail.com>


module mod_sbrot_test
!General comments: solid body rotation test case
!-----------------------------------------------------------------------

!-----------------------------------------------------------------------

 use mod_messages, only: &
   mod_messages_initialized, &
   error,   &
   warning, &
   info

 use mod_kinds, only: &
   mod_kinds_initialized, &
   wp

!-----------------------------------------------------------------------
 
 implicit none

!-----------------------------------------------------------------------

! Module interface

 public :: &
   mod_sbrot_test_constructor, &
   mod_sbrot_test_destructor,  &
   mod_sbrot_test_initialized, &
   test_name, &
   test_description,&
   ndim,      &
   coeff_diff,&
   coeff_adv, &
   coeff_re,  &
   coeff_f,   &
   coeff_dir, &
   coeff_neu, &
   coeff_rob, &
   coeff_init

 private

!-----------------------------------------------------------------------

! Module types and parameters

 ! public members
 character(len=*), parameter ::    &
   test_name = "sbrot"
 integer, parameter ::             &
   ndim = 2

! Module variables

 ! public members
 character(len=100), protected ::    &
   test_description(2)
 logical, protected ::               &
   mod_sbrot_test_initialized = .false.
 ! private members
 real(wp), parameter :: &
   omega = 1.0_wp, & ! angular velocity in rounds/sec
   pi = 3.1415926535897932384626433832795029_wp
 character(len=*), parameter :: &
   this_mod_name = 'mod_sbrot_test'

!-----------------------------------------------------------------------

contains

!-----------------------------------------------------------------------

 subroutine mod_sbrot_test_constructor()
  character(len=*), parameter :: &
    this_sub_name = 'constructor'

   !Consistency checks ---------------------------
   if( (mod_messages_initialized.eqv..false.) .or. &
       (mod_kinds_initialized.eqv..false.) ) then
     call error(this_sub_name,this_mod_name, &
                'Not all the required modules are initialized.')
   endif
   if(mod_sbrot_test_initialized.eqv..true.) then
     call warning(this_sub_name,this_mod_name, &
                  'Module is already initialized.')
   endif
   !----------------------------------------------

   write(test_description(1),'(a)') &
     'Solid body rotation test case'
   write(test_description(2),'(a,e8.3,a)') &
     '  angular velocity = ',omega,' rounds/sec.'

   mod_sbrot_test_initialized = .true.
 end subroutine mod_sbrot_test_constructor

!-----------------------------------------------------------------------
 
 subroutine mod_sbrot_test_destructor()
  character(len=*), parameter :: &
    this_sub_name = 'destructor'
   
   !Consistency checks ---------------------------
   if(mod_sbrot_test_initialized.eqv..false.) then
     call error(this_sub_name,this_mod_name, &
                'This module is not initialized.')
   endif
   !----------------------------------------------

   mod_sbrot_test_initialized = .false.
 end subroutine mod_sbrot_test_destructor

!-----------------------------------------------------------------------
 
 pure function coeff_diff(x) result(mu)
  real(wp), intent(in) :: x(:,:)
  real(wp) :: mu(ndim,ndim,size(x,2))

   mu = 0.0_wp
 end function coeff_diff
 
!-----------------------------------------------------------------------
 
 pure function coeff_adv(x) result(a)
  real(wp), intent(in) :: x(:,:)
  real(wp) :: a(ndim,size(x,2))

   a(1,:) = -2.0_wp*pi*omega*x(2,:)
   a(2,:) =  2.0_wp*pi*omega*x(1,:)
 
 end function coeff_adv
 
!-----------------------------------------------------------------------

 pure function coeff_re(x) result(sigma)
  real(wp), intent(in) :: x(:,:)
  real(wp) :: sigma(size(x,2))
 
   sigma = 0.0_wp

 end function coeff_re
 
!-----------------------------------------------------------------------
 
 pure function coeff_f(x) result(f)
  real(wp), intent(in) :: x(:,:)
  real(wp) :: f(size(x,2))

   f = 0.0_wp
 
 end function coeff_f
 
!-----------------------------------------------------------------------

 pure function coeff_dir(x,breg) result(d)
  real(wp), intent(in) :: x(:,:)
  integer, intent(in) :: breg
  real(wp) :: d(size(x,2))

   d = 0.0_wp

 end function coeff_dir
 
!-----------------------------------------------------------------------

 pure function coeff_neu(x,breg) result(h)
  real(wp), intent(in) :: x(:,:)
  integer, intent(in) :: breg
  real(wp) :: h(size(x,2))

   h = 0.0_wp
 
 end function coeff_neu
 
!-----------------------------------------------------------------------

 pure function coeff_rob(x,breg) result(g)
  real(wp), intent(in) :: x(:,:)
  integer, intent(in) :: breg
  real(wp) :: g(size(x,2))

   g = 0.0_wp
 
 end function coeff_rob
 
!-----------------------------------------------------------------------
 
 pure function coeff_init(x) result(u)
  real(wp), intent(in) :: x(:,:)
  real(wp) :: u(size(x,2))

  integer, parameter :: iinitial = &
 !   1 ! discontinuous datum
    2 ! smooth datum
  real(wp), parameter :: &
    radius = 0.3_wp, &
    center(2) = (/ 0.3_wp , 0.0_wp /)
  real(wp) :: r2(size(x,2))
 
   r2 = (x(1,:)-center(1))**2 + (x(2,:)-center(2))**2
   initial_profile: select case(iinitial)
    case(1)
     where(r2.le.radius**2)
       u = 1.0_wp
     elsewhere
       u = 0.0_wp
     endwhere
    case(2)
     u = exp(-10.0_wp*r2)
   end select initial_profile
     
 end function coeff_init
 
!-----------------------------------------------------------------------

end module mod_sbrot_test

